package cn.kz.hrm.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

@Configuration
@EnableResourceServer //开启资源认证服务
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启全局资源访问。即在要访问的资源上，加上访问需要的权限才可以进行访问。
public class MyResourceServerConfig extends  ResourceServerConfigurerAdapter{

    //设置常量访问的资源的路径或者名字
    private static final String RESOURCE_NAME = "course";

    //设置JWT签名密钥。它可以是简单的MAC密钥，也可以是RSA密钥
    private static final String SIGN_KEY = "123";

    @Autowired
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    //令牌转换器对象JwtAccessTokenConverter(JWT令牌校验工具)，该对象把JWT编码的令牌值和OAuth身份验证信息进行互相转换
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(SIGN_KEY);
        return jwtAccessTokenConverter;
    }

    /**
     * SpringSecurity的相关配置
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 允许的授权范围,传递的是all
                .antMatchers("/**").access("#oauth2.hasScope('all')")
                //关闭跨域伪造
                .and().csrf().disable()
                //因为是使用的token，所有不需要session做数据
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }


    /**
     * 安全的相关的配置
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        //设置访问的资源的名,与token中携带的相同.resourceIds("course")，不相同则不能进行访问
        resources.resourceId(RESOURCE_NAME)
                //通过远程tokenService判断是否是正确的token。
                //.tokenServices(resourceServerTokenServices());
                .tokenStore(tokenStore());//客户端自己校验
        //使用jwt之后不用调用远程进行校验，因为jwt中就封装了所有的信息
    }

    //对资源token进行鉴权，判断，与前台创造的token中的参数要一致
    @Bean
    public ResourceServerTokenServices resourceServerTokenServices(){
        //调用远程token服务。
        RemoteTokenServices tokenServices = new RemoteTokenServices();
        //访问的路径，已经进行放行
        tokenServices.setCheckTokenEndpointUrl("http://localhost:3000/oauth/check_token");
        //客户端的id
        tokenServices.setClientId("webapp");
        //设置客户端的秘钥
        tokenServices.setClientSecret("secret");
        //返回远程的tokenService
        return tokenServices;
    }
}
